package com.sunyur.tailor.channel.service.inner.invoice.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.google.common.collect.Lists;
import com.sunyur.tailor.channel.common.inner.base.SunyurListResult;
import com.sunyur.tailor.channel.common.inner.base.SunyurResult;
import com.sunyur.tailor.channel.common.inner.util.SunyurClientUtil;
import com.sunyur.tailor.channel.common.inner.util.SunyurResultUtil;
import com.sunyur.tailor.channel.common.middle.base.ChannelResult;
import com.sunyur.tailor.channel.common.middle.enums.MiddleResultEnum;
import com.sunyur.tailor.channel.common.middle.util.ChannelListResultUtil;
import com.sunyur.tailor.channel.common.middle.util.ChannelResultUtil;
import com.sunyur.tailor.channel.service.inner.invoice.model.InvoiceHeadModel;
import com.sunyur.tailor.channel.service.inner.invoice.model.InvoiceItemModel;
import com.sunyur.tailor.channel.service.inner.invoice.param.*;
import com.sunyur.tailor.channel.service.inner.invoice.service.SunyurInvoiceService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.List;

/**
 * @ClassName InvoiceService
 * @Description 商城发票服务
 * @Author yu.chen
 * @Date 2021/4/29 4:31
 * @Version 1.0
 **/
@Service("sunyurInvoiceService")
public class SunyurInvoiceServiceImpl implements SunyurInvoiceService {

    private static final Logger LOGGER_INFO = LoggerFactory.getLogger(SunyurInvoiceServiceImpl.class);
    private static final Logger LOGGER_ERROR = LoggerFactory.getLogger(SunyurInvoiceServiceImpl.class);

    /**
     * 请求商越Client
     */
    @Autowired
    private SunyurClientUtil sunyurClient;

    /**
     * 预制发票批量业务确认 链接
     */
    @Value("${sunyur.api.invoiceBusinessBatchConfirm}")
    private String invoiceBusinessBatchConfirm;

    @Value("${sunyur.api.invoiceHeadInfo}")
    private String invoiceHeadInfo;

    @Value("${sunyur.api.invoiceItemListInfo}")
    private String invoiceItemListInfo;

    @Value("${sunyur.api.invoiceConfirm}")
    private String invoiceConfirm;

    @Value("${sunyur.api.invoicePayback}")
    private String invoicePayback;

    @Value("${sunyur.api.payOrderCreate}")
    private String payOrderCreate;


    /**
     * @param invoiceBusinessConfirmParamList
     * @return com.sunyur.tailor.channel.common.middle.base.ChannelResult
     * @description 预制发票批量业务确认
     * @author yu.chen
     * @date 2021/4/29 4:35
     * @Version v1.0
     */
    @Override
    public ChannelResult batchConfirmBusinessInvoice(InvoiceBusinessConfirmParam invoiceBusinessConfirmParamList) throws Exception {
        LOGGER_INFO.info("SunyurInvoiceServiceImpl batchConfirmBusinessInvoice param is {}", JSON.toJSONString(invoiceBusinessConfirmParamList));
        if (ObjectUtils.isEmpty(invoiceBusinessConfirmParamList)) {
            return ChannelListResultUtil.error(MiddleResultEnum.FAILED.getCode(), "SunyurInvoiceServiceImpl batchConfirmBusinessInvoice param is null");
        }
        // 查询参数按长度分割
        List<List<String>> invoiceCodeList = Lists.partition(invoiceBusinessConfirmParamList.getCodes(), 200);
        // 返回错误信息结果集
        List<String> errorMsgList = Lists.newArrayList();
        // 循环调用人员信息同步接口
        for (List<String> strings : invoiceCodeList) {
            // 参数组装
            invoiceBusinessConfirmParamList.setCodes(strings);
            // 调用主线查询采购单行信息接口
            SunyurResult sunyurResult = sunyurClient.execPost(invoiceBusinessBatchConfirm, JSON.toJSONString(invoiceBusinessConfirmParamList), null);
            // 某次调用主线返回错误（本次批次发生错误，记录错误信息，继续调用下一批）
            if (!SunyurResultUtil.isSuccess(sunyurResult)) {
                LOGGER_ERROR.error("batchConfirmBusinessInvoice loop call sunyur request fail, param is {}, result is {}", JSON.toJSONString(invoiceBusinessConfirmParamList), JSON.toJSONString(sunyurResult));
                // 每批次错误信息收集
                errorMsgList.add(sunyurResult.getContent() + "-" + sunyurResult.getErrorMessage());
            }
        }
        // 存在错误信息
        if (!CollectionUtils.isEmpty(errorMsgList)) {
            ChannelListResultUtil.error(MiddleResultEnum.FAILED.getCode(), JSON.toJSONString(errorMsgList));
        }
        return ChannelListResultUtil.success(null);
    }


    /**
     * 指定发票单编号，获取对发票单的头信息
     *
     * @param param
     * @return
     * @author HuBaoding
     * @date 2021年5月17日15:36:03
     */
    @Override
    public ChannelResult<InvoiceHeadModel> getInvoice(InvoiceHeadParam param) {
        SunyurResult<InvoiceHeadModel> sunyurResult = null;
        try {
            sunyurResult = sunyurClient.execPost(invoiceHeadInfo, JSON.toJSONString(param), new TypeReference<SunyurResult<InvoiceHeadModel>>() {
            });
            // 主线返回错误
            if (!SunyurResultUtil.isSuccess(sunyurResult)) {
                return ChannelResultUtil.error(MiddleResultEnum.FAILED.getCode(), sunyurResult.getErrorMessage());
            }
        } catch (Exception e) {
            LOGGER_ERROR.error("SunyurInvoiceServiceImpl getInvoice fail,param is {} ", JSON.toJSONString(param));
            return ChannelResultUtil.error(MiddleResultEnum.FAILED.getCode(), e.getMessage());
        }
        LOGGER_INFO.info("SunyurInvoiceServiceImpl getInvoice param is {} , result is {}", JSON.toJSONString(param), JSON.toJSONString(sunyurResult));
        return ChannelResultUtil.success(sunyurResult.getContent());
    }


    @Override
    public ChannelResult<List<InvoiceItemModel>> listInvoiceOrderItem(InvoiceItemParam invoiceItemParam) throws Exception {
        LOGGER_INFO.info("SunyurInvoiceServiceImpl listInvoiceOrderItem param is {}", JSON.toJSONString(invoiceItemParam));
        if (org.apache.commons.lang3.ObjectUtils.isEmpty(invoiceItemParam) || StringUtils.isBlank(invoiceItemParam.getInvoiceOrderCode())) {
            return ChannelListResultUtil.error(MiddleResultEnum.FAILED.getCode(), "SunyurOrderServiceImpl getOrderListItem param is null");
        }
        // 设置为每页最大条数
        invoiceItemParam.setPage(1);
        invoiceItemParam.setPageSize(100);
        // 调用主线查询采购单头信息接口
        TypeReference<SunyurListResult<InvoiceItemModel>> typeReference = new TypeReference<SunyurListResult<InvoiceItemModel>>() {
        };
        SunyurListResult<InvoiceItemModel> sunyurResult = sunyurClient.execListPost(invoiceItemListInfo, JSON.toJSONString(invoiceItemParam), typeReference);
        // 主线返回错误
        if (!SunyurResultUtil.isSuccess(sunyurResult)) {
            return ChannelListResultUtil.error(MiddleResultEnum.FAILED.getCode(), sunyurResult.getErrorMessage());
        }
        // 判断是否存在下一页
        if (!SunyurResultUtil.isNextPage(sunyurResult)) {
            return ChannelListResultUtil.success(sunyurResult.getContent());
        }

        // 返回结果集
        List<InvoiceItemModel> invoiceItemModelList = Lists.newArrayList();
        // 将第一次查询的结果收集
        invoiceItemModelList.addAll(sunyurResult.getContent());
        // 循环查询剩余数据
        for (int i = invoiceItemParam.getPage() + 1; i <= sunyurResult.getTotalPage(); i++) {
            invoiceItemParam.setPage(i);
            // 调用主线查询采购单头信息接口
            SunyurListResult<InvoiceItemModel> sunyurPageResult = sunyurClient.execListPost(invoiceItemListInfo, JSON.toJSONString(invoiceItemParam), typeReference);
            // 某次调用主线返回错误（小概率，可能网络等原因，此时结果集数据不完整，本次查询失败）
            if (!SunyurResultUtil.isSuccess(sunyurPageResult)) {
                LOGGER_ERROR.error("listInvoiceOrderItem  loop call sunyur request fail, param is {}, result is {}", JSON.toJSONString(invoiceItemParam), JSON.toJSONString(sunyurPageResult));
                return ChannelListResultUtil.error(MiddleResultEnum.FAILED.getCode(), sunyurPageResult.getErrorMessage());
            }
            invoiceItemModelList.addAll(sunyurPageResult.getContent());
        }
        return ChannelListResultUtil.success(invoiceItemModelList);

    }

    @Override
    public ChannelResult singleConfirm(InvoiceReq invoiceReq) throws Exception {
        LOGGER_INFO.info("SunyurInvoiceServiceImpl singleConfirm param is {}", JSON.toJSONString(invoiceReq));
        if (ObjectUtils.isEmpty(invoiceReq)) {
            return ChannelResultUtil.error(MiddleResultEnum.FAILED.getCode(), "SunyurInvoiceServiceImpl singleConfirm param is null");
        }
        // 调用主线接口
        SunyurResult sunyurResult = sunyurClient.execPost(invoiceConfirm, JSON.toJSONString(invoiceReq), null);
        // 主线报错
        if (!SunyurResultUtil.isSuccess(sunyurResult)) {
            return ChannelResultUtil.error(MiddleResultEnum.FAILED.getCode(), sunyurResult.getErrorMessage());
        }
        return ChannelResultUtil.success(sunyurResult.getContent());
    }

    @Override
    public ChannelResult payback(PaybackParam paybackParam) throws Exception {
        LOGGER_INFO.info("SunyurInvoiceServiceImpl payback param is {}", JSON.toJSONString(paybackParam));
        if (ObjectUtils.isEmpty(paybackParam)) {
            return ChannelResultUtil.error(MiddleResultEnum.FAILED.getCode(), "SunyurInvoiceServiceImpl payback param is null");
        }
        // 调用主线接口
        SunyurResult sunyurResult = sunyurClient.execPost(invoicePayback, JSON.toJSONString(paybackParam), null);
        // 主线报错
        if (!SunyurResultUtil.isSuccess(sunyurResult)) {
            return ChannelResultUtil.error(MiddleResultEnum.FAILED.getCode(), sunyurResult.getErrorMessage());
        }
        return ChannelResultUtil.success(sunyurResult.getContent());
    }

    @Override
    public ChannelResult payOrderCreate(PayOrderParam param) throws Exception {
        LOGGER_INFO.info("SunyurInvoiceServiceImpl payOrderCreate param is {}", JSON.toJSONString(param));
        if (ObjectUtils.isEmpty(param)) {
            return ChannelResultUtil.error(MiddleResultEnum.FAILED.getCode(), "SunyurInvoiceServiceImpl payOrderCreate param is null");
        }
        // 调用主线接口
        SunyurResult sunyurResult = sunyurClient.execPost(payOrderCreate, JSON.toJSONString(param), null);
        // 主线报错
        if (!SunyurResultUtil.isSuccess(sunyurResult)) {
            return ChannelResultUtil.error(MiddleResultEnum.FAILED.getCode(), sunyurResult.getErrorMessage());
        }
        return ChannelResultUtil.success(sunyurResult.getContent());
    }
}
